package ginv

import (
	"context"
	"gitee.com/filters/utils/conversion"
	"net/http"
	"reflect"

	"github.com/gin-gonic/gin"
)

// HandlerFunc 定义处理函数类型
type HandlerFunc[Req any, Rsp any] func(ctx context.Context, req *Req, rsp *Rsp) error

// ChainHandler 链式处理器
type ChainHandler struct {
	engine       *gin.Engine
	bindCombo    *conversion.ComboBuilder
	configFile   string
	useBindCombo bool
}

// NewChainHandler 创建新的链式处理器
func NewChainHandler() *ChainHandler {
	return &ChainHandler{
		engine: gin.New(),
	}
}

// WithBindCombo 启用BindCombo功能
func (ch *ChainHandler) WithBindCombo(targets ...interface{}) *ChainHandler {
	ch.bindCombo = conversion.BindCombo(targets...)
	ch.useBindCombo = true
	return ch
}

// WithConfigFile 设置配置文件
func (ch *ChainHandler) WithConfigFile(configFile string) *ChainHandler {
	ch.configFile = configFile
	if ch.bindCombo != nil {
		ch.bindCombo = ch.bindCombo.WithConfigFile(configFile)
	}
	return ch
}

// BuildConfig 构建配置
func (ch *ChainHandler) BuildConfig() *ChainHandler {
	if ch.bindCombo != nil {
		if err := ch.bindCombo.Build(); err != nil {
			panic("Failed to build config: " + err.Error())
		}
	}
	return ch
}

// Use 添加中间件
func (ch *ChainHandler) Use(middleware ...gin.HandlerFunc) *ChainHandler {
	ch.engine.Use(middleware...)
	return ch
}

// GET 注册GET路由
func (ch *ChainHandler) GET(path string, handler interface{}) *ChainHandler {
	ch.registerRoute("GET", path, handler)
	return ch
}

// POST 注册POST路由
func (ch *ChainHandler) POST(path string, handler interface{}) *ChainHandler {
	ch.registerRoute("POST", path, handler)
	return ch
}

// PUT 注册PUT路由
func (ch *ChainHandler) PUT(path string, handler interface{}) *ChainHandler {
	ch.registerRoute("PUT", path, handler)
	return ch
}

// DELETE 注册DELETE路由
func (ch *ChainHandler) DELETE(path string, handler interface{}) *ChainHandler {
	ch.registerRoute("DELETE", path, handler)
	return ch
}

// Group 创建路由组
func (ch *ChainHandler) Group(relativePath string, handlers ...gin.HandlerFunc) *gin.RouterGroup {
	return ch.engine.Group(relativePath, handlers...)
}

// registerRoute 注册路由的通用方法
func (ch *ChainHandler) registerRoute(method, path string, handler interface{}) {
	ginHandler := ch.wrapHandler(handler)
	switch method {
	case "GET":
		ch.engine.GET(path, ginHandler)
	case "POST":
		ch.engine.POST(path, ginHandler)
	case "PUT":
		ch.engine.PUT(path, ginHandler)
	case "DELETE":
		ch.engine.DELETE(path, ginHandler)
	}
}

// wrapHandler 包装处理函数
func (ch *ChainHandler) wrapHandler(handler interface{}) gin.HandlerFunc {
	handlerValue := reflect.ValueOf(handler)
	handlerType := handlerValue.Type()

	// 验证处理函数签名
	if handlerType.Kind() != reflect.Func {
		panic("handler must be a function")
	}

	if handlerType.NumIn() != 3 {
		panic("handler must have exactly 3 parameters: (context.Context, *Req, *Rsp)")
	}

	if handlerType.NumOut() != 1 || handlerType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() {
		panic("handler must return exactly one error")
	}

	// 获取请求和响应类型
	reqType := handlerType.In(1).Elem() // *Req -> Req
	rspType := handlerType.In(2).Elem() // *Rsp -> Rsp

	return func(c *gin.Context) {
		// 创建请求对象
		req := reflect.New(reqType).Interface()

		// 绑定请求参数
		if err := ch.bindRequest(c, req); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"ret": 1,
				"msg": "参数绑定失败: " + err.Error(),
			})
			return
		}

		// 创建响应对象
		rsp := reflect.New(rspType).Interface()

		// 调用处理函数
		ctx := c.Request.Context()
		results := handlerValue.Call([]reflect.Value{
			reflect.ValueOf(ctx),
			reflect.ValueOf(req),
			reflect.ValueOf(rsp),
		})

		// 检查错误
		if !results[0].IsNil() {
			err := results[0].Interface().(error)
			c.JSON(http.StatusInternalServerError, gin.H{
				"ret": 1,
				"msg": "处理失败: " + err.Error(),
			})
			return
		}

		// 返回响应
		c.JSON(http.StatusOK, rsp)
	}
}

// bindRequest 绑定请求参数
func (ch *ChainHandler) bindRequest(c *gin.Context, req interface{}) error {
	// 如果启用了BindCombo，使用增强绑定
	if ch.useBindCombo {
		return ch.bindRequestWithCombo(c, req)
	}

	// 默认绑定方式
	switch c.Request.Method {
	case "GET", "DELETE":
		// 从查询参数绑定
		return c.ShouldBindQuery(req)
	case "POST", "PUT":
		// 优先从JSON绑定，如果失败则从表单绑定
		if err := c.ShouldBindJSON(req); err != nil {
			return c.ShouldBind(req)
		}
		return nil
	default:
		return c.ShouldBind(req)
	}
}

// bindRequestWithCombo 使用BindCombo进行增强绑定
func (ch *ChainHandler) bindRequestWithCombo(c *gin.Context, req interface{}) error {
	// 创建临时BindCombo实例用于请求绑定
	binder := conversion.BindCombo(req)

	// 从不同来源绑定参数
	switch c.Request.Method {
	case "GET", "DELETE":
		// 从查询参数绑定
		if err := c.ShouldBindQuery(req); err != nil {
			return err
		}
	case "POST", "PUT":
		// 从JSON或表单绑定
		if err := c.ShouldBindJSON(req); err != nil {
			if err := c.ShouldBind(req); err != nil {
				return err
			}
		}
	default:
		if err := c.ShouldBind(req); err != nil {
			return err
		}
	}

	// 如果有配置文件，也从配置文件绑定
	if ch.configFile != "" {
		binder = binder.WithConfigFile(ch.configFile)
		if err := binder.Build(); err != nil {
			// 配置文件绑定失败不影响请求处理，只记录日志
			// 这里可以添加日志记录
		}
	}

	return nil
}

// Run 启动服务器
func (ch *ChainHandler) Run(addr ...string) error {
	return ch.engine.Run(addr...)
}

// Engine 获取gin引擎
func (ch *ChainHandler) Engine() *gin.Engine {
	return ch.engine
}

// ServeHTTP 实现http.Handler接口
func (ch *ChainHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	ch.engine.ServeHTTP(w, req)
}
